import { Injectable } from '@nestjs/common';
import * as crypto from 'crypto';
import { createReadStream, existsSync } from 'fs';
import * as fs from 'fs/promises';
import { extname, dirname, join } from 'path';

@Injectable()
export class FileManageService {
  async computeMd5(filePath: string): Promise<string> {
    const ext = extname(filePath) || '.tmp';
    try {
      // 读取文件内容 计算 MD5 哈希
      // const fileBuffer = await fs.readFile(filePath); // readFile 会有较大内存占用,不适合大文件
      // const hash = crypto.createHash('md5').update(fileBuffer).digest('hex');

      // 流方式计算哈希
      const hash = crypto.createHash('md5');
      const stream = createReadStream(filePath);
      const hashStr = await new Promise((resolve, reject) => {
        stream.on('data', (chunk) => hash.update(chunk));
        stream.on('end', () => resolve(hash.digest('hex')));
        stream.on('error', (err) => reject(err));
      });

      // 构建新路径
      const newFileName = `${hashStr}${ext}`;
      const dir = dirname(filePath);
      const newFilePath = join(dir, newFileName);
      // 存在就删除原文件后返回文件名
      if (existsSync(newFilePath)) {
        fs.unlink(filePath);
        return newFileName;
      }
      // 不存在就重命名返回
      await fs.rename(filePath, newFilePath);
      return newFileName;
    } catch (error) {
      const fallbackName = `${Date.now()}-${Math.random()}${ext}`;
      return fallbackName;
    }
  }
}
